package speed2010.reformulacao.query;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.Vector;

import javax.swing.JOptionPane;

import speed2010.reformulacao.useful.Standards;
import edu.stanford.smi.protegex.owl.model.query.QueryResults;
public class ReformulationProperties {

	public Vector<String> getProperties(String propQuery) {
		Vector<String> properties = new Vector<String>();

		int indexProperty = propQuery.indexOf("#");
		String subString = propQuery.substring(indexProperty + 1, propQuery.length());

		int sizeProperty = 0;
		int controlProperty = 0;

		while (subString.contains("#")) {
			indexProperty = subString.indexOf("#");
			controlProperty = indexProperty;
			while (subString.charAt(controlProperty + 1) != '>') {
				sizeProperty++;
				controlProperty++;
			}

			properties.add(subString.substring(indexProperty + 1, indexProperty + 1 + sizeProperty));

			sizeProperty = 0;
			controlProperty = 0;
			subString = subString.substring(indexProperty + 1, subString.length());
		}

		return properties;
	}

	public String getConcept(String propQuery) {
		int indexConcept = propQuery.indexOf("#");
		int sizeConcept = 0;
		int controlConcept = indexConcept;

		while (propQuery.charAt(controlConcept + 1) != '>') {
			sizeConcept++;
			controlConcept++;
		}

		String concept = propQuery.substring(indexConcept + 1, indexConcept + 1 + sizeConcept);

		return concept;
	}

	/**
	 * Find related concepts to the one in the parameter
	 * 
	 * @param fileCorrespondences
	 * @param fileSource
	 * @param concept
	 * @return
	 * @throws FileNotFoundException
	 */
	public Vector<String> getRelatedConcepts(String fileCorrespondences, String fileSource, String concept)
			throws FileNotFoundException {
		SparqlQuery sparql = new SparqlQuery();
		String peerIdentifier = sparql.getHeaderElement("xml:base", fileSource);

		Vector<String> relatedConcepts = this.findConceptCorrespondences(fileCorrespondences, concept, peerIdentifier);

		return relatedConcepts;
	}

	/**
	 * Equivalence correspondence
	 * 
	 * @param fileCorrespondences
	 * @param fileSource
	 * @param properties
	 * @return
	 * @throws FileNotFoundException
	 */
	public Vector<String> getEquivalentProperties(String fileCorrespondences, String fileSource,
			Vector<String> properties) throws FileNotFoundException {
		SparqlQuery sparql = new SparqlQuery();
		String peerIdentifier = sparql.getHeaderElement("xml:base", fileSource);

		Vector<String> equivalentProperties = new Vector<String>();

		for (int i = 0; i < properties.size(); i++) {
			Vector<String> tempEqProp = this.findPropertyCorrespondences(fileCorrespondences, properties.elementAt(i),
					peerIdentifier);
			for (int j = 0; j < tempEqProp.size(); j++) {
				equivalentProperties.add(tempEqProp.elementAt(j));
			}
		}

		return equivalentProperties;

	}

	/**
	 * SPARQL Format
	 * 
	 * @param relatedConcepts
	 * @param equivalentProperties
	 * @return
	 * @throws FileNotFoundException
	 */
	public Vector<String> treatPropertiesQuery(Vector<String> relatedConcepts, Vector<String> equivalentProperties)
			throws FileNotFoundException {

		return this.generateReformulatedQueries(relatedConcepts, equivalentProperties);

	}

	/**
	 * SPARQL Format (already has the concepts and properties)
	 * 
	 * @param concepts
	 * @param properties
	 * @return
	 */
	private Vector<String> generateReformulatedQueries(Vector<String> concepts, Vector<String> properties) {

		Vector<String> queries = new Vector<String>();
		SparqlQuery sparql = new SparqlQuery();
		String entityElement = "";

		try {
			entityElement = sparql.getHeaderElement("xml:base", Standards.fileDestiny);
		} catch (FileNotFoundException e) {
			JOptionPane.showMessageDialog(null, "File not found");
		}

		String preQuery = "";
		int quantProperties = properties.size();

		if (quantProperties > 0) {
			for (int i = 0; i < concepts.size(); i++) {
				preQuery = "SELECT ?x ";
				for (int j = 0; j < quantProperties; j++) {
					preQuery += "?prop" + (j + 1) + " ";
				}
				preQuery += "\n";
				preQuery += "FROM <" + entityElement + ">\n";
				preQuery += "WHERE {\n";
				preQuery += "?x rdf:type <" + entityElement + "#" + concepts.elementAt(i) + "> .\n";
				preQuery += "{ \n";
				for (int j = 0; j < quantProperties; j++) {
					preQuery += "?x <" + entityElement + "#" + properties.elementAt(j) + "> ?prop" + (j + 1) + "\n";
					if (j != quantProperties - 1) {
						preQuery += "} UNION {\n";
					}
				}
				preQuery += "} } \n";

				queries.add(preQuery);
				preQuery = "";

			}
		}

		return queries;

	}

	/**
	 * Correspondences between properties
	 * 
	 * @param fileCorrespondences
	 * @param property
	 * @param peerIdentifier
	 * @return
	 * @throws FileNotFoundException
	 */
	private Vector<String> findPropertyCorrespondences(String fileCorrespondences, String property,
			String peerIdentifier) throws FileNotFoundException {
		Scanner scProperty = new Scanner(new File(fileCorrespondences));

		Vector<String> equivalentProperties = new Vector<String>();

		while (scProperty.hasNext()) {
			String line = scProperty.nextLine().trim();
			if (line.contains("rdf:about") && line.contains(peerIdentifier)) {
				String lineProperty = line.substring(line.lastIndexOf('#') + 1, line.lastIndexOf('"'));
				if (property.equals(lineProperty)) {
					line = scProperty.nextLine().trim();
					while (!line.equals("</rdf:Description>")) {
						if (line.contains("isEquivalentTo")) {
							equivalentProperties.add(line.substring(line.lastIndexOf('#') + 1, line.lastIndexOf('<')));
						}
						line = scProperty.nextLine().trim();
					}
					break;
				}
			}
		}// external while

		return equivalentProperties;

	}

	/**
	 * Correspondences of the concept
	 * 
	 * @param fileCorrespondences
	 * @param concept
	 * @param peerIdentifier
	 * @return
	 * @throws FileNotFoundException
	 */
	public Vector<String> findConceptCorrespondences(String fileCorrespondences, String concept, String peerIdentifier)
			throws FileNotFoundException {
		Scanner scConcept = new Scanner(new File(fileCorrespondences));

		Vector<String> relatedConcepts = new Vector<String>();

		while (scConcept.hasNext()) {
			String line = scConcept.nextLine().trim();
			if (line.contains("rdf:about") && line.contains(peerIdentifier)) {
				String lineConcept = line.substring(line.lastIndexOf('#') + 1, line.lastIndexOf('"'));
				if (concept.equals(lineConcept)) {
					line = scConcept.nextLine().trim();
					// Getting the correspondent elements
					while (!line.equals("</rdf:Description>")) {
						if (line.contains("isEquivalentTo") || line.contains("isSuperConceptOf")
								|| line.contains("isSubConceptOf") || line.contains("isCloseTo")) {

							relatedConcepts.add(line.substring(line.lastIndexOf('#') + 1, line.lastIndexOf('<')));

						}
						line = scConcept.nextLine().trim();
					}
					break;
				}
			}
		}// external while

		return relatedConcepts;
	}

	/**
	 * Execute the query
	 * 
	 * @param path
	 * @param query
	 * @return
	 */
	public QueryResults execQuery(String path, String query) {
		QueryResults results = null;
		System.out.println(query);
		try {
			results = QueryProtege.execSearch(path, query);

		} catch (Exception e) {
			e.printStackTrace();
			JOptionPane.showMessageDialog(null, "Problem(s) encountered to execute the query", "Query Error",
					Standards.ERROR_MSG);
		}

		return results;
	}

}
